package com.etlmaster.executor.utils;

import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.springframework.util.StringUtils;

import com.etlmaster.core.DataSourceDefine;
import com.etlmaster.core.DataSourceHolder;
import com.etlmaster.executor.utils.LogWriter;



/**
 * @author Larry
 * @copyright Larry@etlMaster
 * @since 2017-09-10
 */
public class ImpalaUtil {
	private static final String split=";";
	private static final String split_unit="=";
	private static final String dacp_define_flag="dacp.";
	public static final String JAASNAME="jaas.name";
	//private static ConcurrentHashMap<String,String> user_define_domain=new ConcurrentHashMap<String,String>();
	/**
	 * 由于impala采用和hive同样的驱动，所以需要通过url来区分
	 * @param url
	 * @return
	 */
	public static boolean isImpala(String url){
		if(StringUtils.isEmpty(url)){
			return false;
		}
		if(url.indexOf("impala")>0 || url.indexOf("IMPALA")>0){
			return true;
		}
		return false;
	}
	public static boolean checkImpala(String dsName){
		DataSourceDefine dfs = DataSourceHolder.getInstance()
				.getDataSourceDefine(dsName);
		if(null==dfs){
			return false;
		}else if(ImpalaUtil.isImpala(dfs.getUrl())){
			LogWriter.addLog("DEBUG", "impala数据源:", dsName);
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 增加自定义url参数，写入system.property
	 * @param url
	 * @return 返回处理后的驱动url
	 */
	public static String dealUrl(String url){
		if(StringUtils.isEmpty(url)){
			return url;
		}
		LogWriter.addLog("DEBUG",
				"URL处理初始值：{}",url);
		String ret_url=url;
		String[] _urllist=url.split(split);
		for(String _unit:_urllist){
			//1.识别dacp自定义属性
			if(checkUserDefine(_unit)){
				if(checkValidata(_unit)){
					//2.自定义参数写入property
					setProperty(_unit.split(split_unit)[0].substring(dacp_define_flag.length()),_unit.split(split_unit)[1]);
					ret_url=ret_url.replaceAll(_unit, "");
					
				}else{
					LogWriter.addLog("ERROR",
							"自定义参数错误,错误段：{}",_unit);
				}
			}
		}
		//3.url去除自定义参数段并返回
		ret_url=ret_url.replaceAll("[;]+", split);
		LogWriter.addLog("DEBUG",
				"URL处理返回值：{}",ret_url);
		
		return ret_url;
	}
	
	private static boolean checkValidata(String unit){
		if(StringUtils.isEmpty(unit)){
			return false;
		}
		return unit.indexOf(split_unit)>0;
	}
	/**
	 * 检查url单元是否为dacp自定义
	 * @param unit
	 * @return
	 */
	private static boolean checkUserDefine(String unit){
		if(StringUtils.isEmpty(unit)){
			return false;
		}
		unit=unit.trim();
		if(unit.startsWith(dacp_define_flag) && unit.length()>dacp_define_flag.length())
			return true;
		return false;
	}
	private static void setProperty(String key,String value){
		if(StringUtils.isEmpty(key)||StringUtils.isEmpty(value)){
			return;
		}
		if(key.startsWith("."))
			key=key.substring(1);
		System.setProperty(key, value);
		LogWriter.addLog("DEBUG",
				"设置系统参数：key[{}],value[{}]",key,value);
	}
	/**
	 * @param driverName
	 * @param _url
	 * @param userName
	 * @param passWord
	 * @return
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 * @throws LoginException
	 * @throws PrivilegedActionException
	 */
	public static Connection getConnection(final String driverName, String _url,final String userName, final String passWord)
			throws ClassNotFoundException, SQLException, LoginException, PrivilegedActionException {
		// 处理url
		final String url = dealUrl(_url);
		Class.forName(driverName);
		Connection conn = null;
		// * 现场人员提供的认证连接方式
		if(!StringUtils.isEmpty(System.getProperty(JAASNAME)) ){
			LoginContext lc = new LoginContext(System.getProperty(JAASNAME), new MyCallbackHandler());
			lc.login();
			Subject subject = lc.getSubject();
			// 登录成功构造Connection连接
			conn = (Connection) Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
				public Object run() {
					try {
						Class.forName(driverName);
						//return DriverManager.getConnection(url,userName,passWord);
						return DriverManager.getConnection(url);
					} catch (ClassNotFoundException e) {
						LogWriter.addLog("ERROR","找不到类：{}",e.getMessage());
					} catch (SQLException e) {
						LogWriter.addLog("ERROR","SQL异常：{}",e.getMessage());
					}
					return null;
				}
			});
		}else{
			conn=getConn(driverName, _url, userName, passWord);
		}
		return conn;
	}
	/**
	 * 
	 * @param driverClassName
	 * @param url
	 * @param userName
	 * @param passWord
	 * @return
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static Connection getConn(String driverClassName, String url, String userName, String passWord)
			throws ClassNotFoundException, SQLException {
		url = dealUrl(url);
		Class.forName(driverClassName);
		Connection connection = null;
		connection = DriverManager.getConnection(url, userName, passWord);

		return connection;
	}
	
	
	
	
	public static void main(String[] args){
		String url = "jdbc:hive2://10.78.152.122:28041/;"
                + "principal=impala/haproxyfloatname@HADOOP.COM;"
                + "auth=kerberos;sasl.qop=auth;kerberosAuthType=fromSubject;"
				+ "dacp.java.security.krb5.conf=/root/fi_client/impala_test/krb5.conf;"
                + "dacp.java.security.auth.login.config=/root/fi_client/impala_test/jaas.conf;"
                + "dacp.jaas.name=client";
		
		dealUrl(url);
		LogWriter.addLog("INFO",System.getProperty(JAASNAME));
	}

}
class MyCallbackHandler implements CallbackHandler
{
    public void handle(Callback[] callbacks) throws IOException,
            UnsupportedCallbackException
    {
    }
}
